package dmp.frame.java.agent.transformer;

import dmp.frame.java.agent.transformer.impl.RibbonRequestTransformer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.lang.instrument.ClassFileTransformer;
import java.lang.instrument.IllegalClassFormatException;
import java.lang.instrument.Instrumentation;
import java.security.ProtectionDomain;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

//管理器
public class TransformerManager {
    private static final Logger log = LoggerFactory.getLogger(TransformerManager.class);

    public static void registryTransformer(Instrumentation inst) {
        CompoundTransformer compoundTransformer = new CompoundTransformer();
//        //feign
//        compoundTransformer.register(new TomcatTransformer());
//        //tomcat
//        compoundTransformer.register(new FeignHttpClientTransformer());
        //consul
        //compoundTransformer.register(new ConsulRegistryTransformer());
        //ribbon
        compoundTransformer.register(new RibbonRequestTransformer());
        inst.addTransformer(compoundTransformer);
    }

    public static class CompoundTransformer implements ClassFileTransformer {
        private Map<String, MyTransformer> myTransformerMap = new HashMap<>();
        @Override
        public byte[] transform(ClassLoader loader, String className, Class<?> classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer) throws IllegalClassFormatException {
            if (className == null) {
                return classfileBuffer;
            }
            try {

                MyTransformer myTransformer = this.myTransformerMap.get(className);
                if (myTransformer != null) {
                    return myTransformer.transform(loader, className, classBeingRedefined, protectionDomain, classfileBuffer);
                }
            } catch (Throwable e) {
                log.error( "failed to change byte code for class{}:",className,e);
            }
            return classfileBuffer;
        }

        public void register(MyTransformer myTransformer) {
            Set<String> names = myTransformer.getNames();
            if (names != null && names.size() > 0) {
                for (String name : names) {
                    this.myTransformerMap.put(name, myTransformer);
                }
            }
        }
    }
}


